<?php
///
namespace lxsphp;

/**
 * 框架核心实例
 *
 * @version $Id: Instance.php 195 2014-07-18 09:35:22Z linsir123 $
 * @package lxsphp
 */
class Instance
{
	/**
	 * 应用别名
	 * // 用于改变控制器和视图层的目录结构
	 *
	 * @var array
	 */
	public $alias;

	/**
	 * 实例对象集合
	 *
	 * @var array
	 */
	public $instances = array();

	/**
	 * 返回`错误/异常处理`对象
	 *
	 * @return Core\Handler
	 */
	public function getHandler()
	{
		///
		return $this->singleton('lxsphp\Core\Handler');
	}

	/**
	 * 返回`配置`管理对象
	 *
	 * @return Core\Config
	 */
	public function getConfig()
	{
		///
		return $this->singleton('lxsphp\Core\Config');
	}

	/**
	 * 返回`日志`对象
	 *
	 * @return Core\Log
	 */
	public function getLog()
	{
		///
		return $this->singleton('lxsphp\Core\Log');
	}

	/**
	 * 返回`调试`对象
	 *
	 * @return Core\Debugger
	 */
	public function getDebugger()
	{
		///
		return $this->singleton('lxsphp\Core\Debugger');
	}

	/**
	 * 返回`勾子`管理对象
	 *
	 * @return Core\Hook
	 */
	public function getHook()
	{
		///
		return $this->singleton('lxsphp\Core\Hook');
	}

	/**
	 * 返回`链接请求`对象
	 *
	 * @return Core\Mvc\Request
	 */
	public function getRequest()
	{
		///
		return $this->singleton('lxsphp\Core\Mvc\Request');
	}

	/**
	 * 返回`消息派发`对象
	 *
	 * @return Core\Mvc\Dispatcher
	 */
	public function getDispatcher()
	{
		///
		return $this->singleton('lxsphp\Core\Mvc\Dispatcher');
	}

	/**
	 * 返回`视图`对象
	 *
	 * @return Core\Mvc\View
	 */
	public function getView()
	{
		///
		return $this->singleton('lxsphp\Core\Mvc\View');
	}

	/**
	 * 取得一个存储对象
	 *
	 * @param string $store 存储器
	 * @param string $index 索引
	 *
	 * @throws \Exception
	 * @return mixed
	 */
	public function getStore($store, $index)
	{
		///
		$list = ['Redis', 'Pdo'];
		if (! in_array($store, $list))
			throw new \Exception("[APP] 存储引擎不存在({$store})");

		///
		$class = sprintf("lxsphp\\Store\\%s\\%s", $store, $store);

		///
		if (! $this->isSingleton($class, $index)) {
			$key = sprintf("store.%s.%s", strtolower($store), $index);
			$conf = $this->getConfig()->get($key);
			$params = array($conf);
		}
		else
			$params = null;

		///
		return $this->singleton($class, $params, $index);
	}

	/**
	 * 返回一个数据表模型对象
	 *
	 * @param string $class 类名（相对App/Db）
	 *
	 * @return mixed
	 */
	public function getDb($class)
	{
		///
		$class = "Db\\" . $class;
		$file = APP_DIR . str_replace("\\", "/", $class) . ".php";
		Load::addClass($class, $file);

		///
		return $this->singleton($class);
	}

	/**
	 * 返回一个模型对象
	 *
	 * @param string $class 类名（相对App/Model）
	 * @param int $key 同一个类的某个实例(0则返回某个实例, 非0则为某个单例)
	 *
	 * @return mixed
	 */
	public function getModel($class, $key = 1)
	{
		///
		$class = "Model\\" . $class;
		$file = APP_DIR . str_replace("\\", "/", $class) . ".php";
		Load::addClass($class, $file);

		///
		return $key === 0 ?
			$this->newInstance($class, null) :
			$this->singleton($class, null, $key);
	}

	/**
	 * 取得一个插件
	 *
	 * @param $class $name 组件名
	 * @param bool $internal 从应用或框架处提供
	 *
	 * @return mixed
	 */
	public function getHelper($class, $internal = true)
	{
		///
		$prefix = $internal
			? "lxsphp\\Helper\\" : "Helper\\";

		$class = $prefix . $class;
		$file = APP_DIR . str_replace("\\", "/", $class) . ".php";
		Load::addClass($class, $file);

		///
		return $this->singleton($class, null);
	}

	/**
	 * 判断某个类是否实例化
	 *
	 * @param string $class 类名
	 * @param int $key 同名类时,区间的键值
	 *
	 * @return bool
	 */
	public function isSingleton($class, $key = 0)
	{
		///
		return isset($this->instances[$class][$key]);
	}

	/**
	 * 取得某个类的实例化对象
	 *
	 * @param string $class 类名
	 * @param array $params 类实例化时需要的参数
	 * @param int $key 同一个类的某个实例
	 *
	 * @throws \Exception
	 * @return mixed
	 */
	public function singleton($class, $params = array(), $key = 0)
	{
		///
		if ($this->isSingleton($class, $key))
			return $this->instances[$class][$key];

		///
		if (! class_exists($class))
			throw new \Exception("[APP] 类不存在({$class})");

		///
		$singleton = $this->newInstance($class, $params);
		$this->instances[$class][$key] = $singleton;

		return $singleton;
	}

	/**
	 * 返回某个类的实例
	 *
	 * @param string $class 类名
	 * @param array $params 类实例化时需要的参数
	 *
	 * @return mixed
	 */
	public function newInstance($class, $params = array())
	{
		///
		if (count($params) == 0)
			return new $class;

		///
		$ref = new \ReflectionClass($class);

		return $ref->newInstanceArgs($params);
	}

	/**
	 * 启动应用程序
	 *
	 * @param string $route 路由信息
	 */
	public function serve($route = null)
	{
		///
		$this->_init();

		///
		$data = $this->getRequest()->parse($route);
		$this->getHook()->activeHook('dispatcher_start', $data);

		///
		list($this->alias, $v) = $data;
		$this->getDispatcher()->gotoCtrl($v[0], $v[1]);

		///
		$this->end();
	}

	/**
	 * 结束应用并输出结果
	 */
	public function end()
	{
		///
		if ($this->isSingleton('lxsphp\Core\Mvc\View'))
			$this->getView()->render();

		///
		$this->getHook()->activeHook('end');

		///
		exit();
	}

	/**
	 * 初始化
	 */
	private function _init()
	{
		///
		if (function_exists('date_default_timezone_set'))
			date_default_timezone_set('Asia/ShangHai');

		///
		Load::addClassByDir(APP_DIR . "Lib/", array('Init'), 1);

		/// Handler
		$this->getHandler()->init();
	}
}
